/**
 * 调整的主要目的有两个:
 * 一是方便于和Extjs2.0.2整合使用
 * 二是简化数据来往，并使得其服务更加单一化，而不是成为一个大而全的东西
//---------------1
function _store(reader){
	var ds = new Ext.data.Store({
		proxy: new Ext.data.JsonRpcProxy({
			action: "MyTestRpc.hello"
		}), 
		reader: reader
	});
	return ds;
}
var r = new Ext.data.JsonReader({
	totalProperty: 'totalProperty',
	root: 'root',
	fields: ["result"]
});
var ds1 = _store(r);
ds1.load({params: ["测,,,试a", 202]});
//---------------2
var r = __rpc_.service("MyTestRpc.hello", {params: ["测,,,试a", 202]});
alert(r.result);

var ro = __rpc_.invoke("MyTestRpc.hello", ["测试", 202]);
alert(ro);
//---------------3
<a href='/JRPC?__p={"action":"MyTestRpc.hello","params":["测试",202]}'>Test</a>
*/
function _jsonRpcExt(url) {
	url || (url = ("undefined" === typeof contextPath ? "." : contextPath) + "/JRPC");
	this["url"] = url;
	var _this = this, bind = function (f, o) {
		return function () {
			return f.apply(o, arguments);
		};
	}, _A = function (p) {
		var r = [], i = 0, j = p.length;
		for (; i < j; i++) {
			r.push(p[i]);
		}
		return r;
	}, AJAX = function (o) {
		if (window === this)
			return new AJAX(o);
		var _this = this;
		if (this.xml = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest()) {
			this.xml.open("POST", o.url, o.bAsync, "", "");
			this.xml.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
			this.xml.setRequestHeader("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Alexa Toolbar; Maxthon 2.0)");
			this.xml.onreadystatechange = function () {
				if (4 === _this.xml.readyState) {
					200 === _this.xml.status && o.clbkFun && o.clbkFun(_this.xml), delete _this.xml.onreadystatechange, delete _this.xml;
				}
			};
			this.xml.send(o.data && o.data.replace(/[\u4E00-\u9FA5]/gm, function(){
			   return "&#" + arguments[0].charCodeAt(0) + ";";
			}) || "");
		}
	};
	// private
	var request = function () { // 这里传入的参数是方法的参数值 
		var params = _A(arguments), bAsync = false, result = {};
		var action = params[0], data = (function (arg) {
			var b = [], szTp;
			for (var i = 0; i < arg.length; i++) {
				if ("number" === (szTp = typeof arg[i]) || "boolean" === szTp)
					b.push(arg[i]);
				else
					b.push("\"" + (arg[i] || "").toString().replace(/([\r\n\t\b\f"])/gm, "\\$1") + "\"");
			}
			return "[" + b.join(",") + "]";
		})(params[1]), clbkFun = params[2];
		//alert(data.length + "--url=" + this.url + " | data=" + ("{\"action\":\"" + action + "\",\"params\":" + data + "}") + " | clbkFun=" + clbkFun);
		AJAX({url:this.url, bAsync:bAsync, 
			data: "{\"action\":\"" + action + "\",\"params\":" + data + "}",
			clbkFun: clbkFun ? clbkFun : function(r){result = r;}});			
		if(!clbkFun){return result.responseText;}
	};
	// 仅增加处理返回的数据，这里供直接调用时使用，不是给extjs直接用的，但是返回的值需要是{result:'值'}格式
	this["invoke"] = function (_action, _params) {
		var r = _this.service(_action, _params);
		eval("var oTmp = " + r);
		return (typeof oTmp != "undefined") ? oTmp.result : -1; 
	};
	this["service"] = bind(request, {url:_this.url});
}
var __rpc_ = new _jsonRpcExt();

Ext.data.JsonRpcProxy = function(c){
    Ext.data.JsonRpcProxy.superclass.constructor.call(this);
    this.action = c.action;
};

Ext.extend(Ext.data.JsonRpcProxy, Ext.data.DataProxy, {
    load : function(params, reader, callback, scope, arg){
        if(this.fireEvent("beforeload", this, params) !== false){       	
            var  o = {
                params : params || {},
                request: {
                    callback : callback,
                    scope : scope,
                    arg : arg
                },
                reader: reader,
                callback : this.loadResponse,
                scope: this
            };
            var _params = o.params;
			if(isNaN(o.params.length)){ // 判断是否数据，如果不是，则需要调整参数，如果没有，表示不是数组，则需要根据具体情况做处理了
				// 如果start和limit都有值，则说明是pagingbar使用的参数，做处理
				if((typeof o.params.start) != "undefined" && (typeof o.params.limit) != "undefined"){
					if((typeof o.params.vv) != "undefined")
						_params = [o.params.start, o.params.limit, o.params.vv];
					else
						_params = [o.params.start, o.params.limit];
				}
			}
            __rpc_.service(this.action, _params, function(r,e){
            	o.callback.call(o.scope, o, r && !e, r || e);
            });
        }else{
            callback.call(scope||this, null, arg, false);
        }
    },

    // private
    loadResponse : function(o, success, response){
        if(!success){
            this.fireEvent("loadexception", this, o, response);
            o.request.callback.call(o.request.scope, null, o.request.arg, false);
            return;
        }
        var result;                
        try {        	
            result = o.reader.read(response);
        }catch(e){
        	alert(response + "**" + e.message);
            this.fireEvent("loadexception", this, o, response, e);
            o.request.callback.call(o.request.scope, null, o.request.arg, false);
            return;
        }
        this.fireEvent("load", this, o, o.request.arg);
        o.request.callback.call(o.request.scope, result, o.request.arg, true);
    },
    
    update : function(dataSet){},
    updateResponse : function(dataSet){}
});